package com.aopeng.service.impl;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.model.PicturesTable;
import org.apache.poi.hwpf.usermodel.CharacterRun;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Table;
import org.apache.poi.hwpf.usermodel.TableCell;
import org.apache.poi.hwpf.usermodel.TableIterator;
import org.apache.poi.hwpf.usermodel.TableRow;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

/**
 * word文件解析类，无法解析word中的编码等等...
 * 2020-11-26 15:09 cjh
 */
@Service
@Component
@Configuration
@EnableScheduling
public class WordExcelToHtml {

    /**
     * 回车符ASCII码
     */
    private static final short ENTER_ASCII = 13;

    /**
     * 空格符ASCII码
     */
    private static final short SPACE_ASCII = 32;

    /**
     * 水平制表符ASCII码
     */
    private static final short TABULATION_ASCII = 9;

    public String htmlText = "";
    public String htmlTextTbl = "";
    public int counter=0;
    public int beginPosi=0;
    public int endPosi=0;
    public int beginArray[];
    public int endArray[];
    public String htmlTextArray[];
    public boolean tblExist=false;
    public String imgPath = "/usr/local/tomcat/image";

    /** 解析docx文件主方法 ,返回style文章样式和div文章内容
     * @param is 文件流
     */
    public String getDocxWordToHtml(FileInputStream is) {
        XWPFDocument xwpfDocument = null;
        String content = null;
        XHTMLOptions options = null;
        try {
            xwpfDocument = new XWPFDocument(is);
            options = XHTMLOptions.create().indent(4);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            List<XWPFPictureData> pictureDatas = xwpfDocument.getAllPictures();
            //保存图片
            HashMap<String,Object> printImg = printImg(pictureDatas);
            XHTMLConverter.getInstance().convert(xwpfDocument, baos, options);
            content = baos.toString();
            String beginStyle = "<style>";
            String endStyle = "</style>";
            String style = content.substring(content.indexOf(beginStyle), content.indexOf(endStyle)+endStyle.length());
            List<String> regexString = getRegexString(content,"<img.*>|<img.*/>");
            //更换图片路径
            for (int i = 0; i < regexString.size(); i++) {
                String x = regexString.get(i);
                List<String> regexString2 = getRegexString(x,"src=\"(\\S*?)[^\"]*\".*?");
                String substring = regexString2.get(0)
                    .substring(regexString2.get(0).lastIndexOf("/") + 1, regexString2.get(0).lastIndexOf("."));
                String replaceAll = x.replaceAll("src=\"(\\S*?)[^\"]*\".*?", "src=\""+printImg.get(substring)+"\"");
                content = content.replaceAll(x, replaceAll);
            }
            //获取div里的样式
            String s = getRegexString(content, "<div style=\"(\\S*?)[^\"]*\".*?>").get(0);
            //去掉样式
            String s1 = s.replaceAll("style=\"(\\S*?)[^\"]*\".*?", "");
            content = content.replaceAll(s, s1);//更新
            //截取div部分，其他全舍弃
            String beginDiv = "<div >";
            String endDiv = "</div>";
            String div = content.substring(content.indexOf(beginDiv), content.indexOf(endDiv)+endDiv.length());
            content = style+div;
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return content;
    }

    /**
     * 将word中的图片保存到指定位置
     * @param sheetList
     * @return
     * @throws IOException
     */
    public HashMap<String,Object> printImg(List<XWPFPictureData> sheetList) throws IOException {
        HashMap<String,Object> list = new HashMap<String, Object>();
        File file = new File(imgPath);
        if (!file.exists()){
            file.mkdirs();
        }
        for (XWPFPictureData pdata : sheetList) {
            String fileExt =  pdata.getFileName().substring(pdata.getFileName().lastIndexOf(".") + 1);
            String fileName =  pdata.getFileName().substring(0,pdata.getFileName().indexOf("."));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd+HH-mm-ss");
            String time = sdf.format(new Date());
            byte[] data = pdata.getData();
            String img = imgPath+File.separatorChar+ time + fileName + "." + fileExt;
            list.put(fileName,"/img/word/"+ time + fileName + "." + fileExt);//添加到结果集
            FileOutputStream out = new FileOutputStream(img);
            out.write(data);
            out.close();
        }
        System.out.println(imgPath);
        return list;
    }
    /**
     * 获取正则匹配的字符串
     * @param str 待匹配的字符串
     * @param regex  正则
     * @return
     */
    public List<String> getRegexString(String str,String regex){
        Pattern patten = Pattern.compile(regex);//编译正则表达式
        Matcher matcher = patten.matcher(str);// 指定要匹配的字符串
        List<String> matchStrs = new ArrayList<>();
        while (matcher.find()) { //此处find（）每次被调用后，会偏移到下一个匹配
            matchStrs.add(matcher.group());//获取当前匹配的值
        }
        return matchStrs;
    }

    /** 解析doc文件主方法
     * 读取每个文字样式
     *
     * @param is 文件流
     * @throws Exception
     */
    public String getWordAndStyle(FileInputStream is) throws Exception {
        HWPFDocument doc = new HWPFDocument(is);
        Range rangetbl = doc.getRange();//得到文档的读取范围
        TableIterator it = new TableIterator(rangetbl);
        int length = doc.characterLength();
        beginArray=new int[length];
        endArray=new int[length];
        htmlTextArray=new String[length];
        // 取得文档中字符的总数
        // 创建图片容器
        PicturesTable pTable = doc.getPicturesTable();
//        htmlText = "<html><head><title>" + doc.getSummaryInformation().getTitle() + "</title></head><body>";
        htmlText = "<div >";
        // 创建临时字符串,好加以判断一串字符是否存在相同格式
        if(it.hasNext())
        {
            readTable(it,rangetbl);
        }
        int cur=0;
        String tempString = "";
        for (int i = 0; i < length - 1; i++) {
            // 整篇文章的字符通过一个个字符的来判断,range为得到文档的范围
            Range range = new Range(i, i + 1, doc);
            CharacterRun cr = range.getCharacterRun(0);
            if(tblExist)
            {
                if(i==beginArray[cur])
                {
                    htmlText+=tempString+htmlTextArray[cur];
                    tempString="";
                    i=endArray[cur]-1;
                    cur++;
                    continue;
                }
            }
            if (pTable.hasPicture(cr)) {
                htmlText +=  tempString ;
                // 读写图片
                readPicture(pTable, cr);
                tempString = "";
            }
            else {

                Range range2 = new Range(i + 1, i + 2, doc);
                // 第二个字符
                CharacterRun cr2 = range2.getCharacterRun(0);
                char c = cr.text().charAt(0);

                System.out.println(i+"::"+range.getEndOffset()+"::"+range.getStartOffset()+"::"+c);

                // 判断是否为回车符
                if (c == ENTER_ASCII)
                {
                    tempString += "<br/>";

                }
                // 判断是否为空格符
                else if (c == SPACE_ASCII)
                    tempString += " ";
                    // 判断是否为水平制表符
                else if (c == TABULATION_ASCII)
                    tempString += "    ";
                // 比较前后2个字符是否具有相同的格式
                boolean flag = compareCharStyle(cr, cr2);
                if (flag)
                    tempString += cr.text();
                else {
                    String fontStyle = "<span style=\"font-family:" + cr.getFontName() + ";font-size:" + cr.getFontSize() / 2 + "pt;";

                    if (cr.isBold())
                        fontStyle += "font-weight:bold;";
                    if (cr.isItalic())
                        fontStyle += "font-style:italic;";

                    /*htmlText += fontStyle + "\" mce_style=\"font-family:" + cr.getFontName() + ";font-size:" + cr.getFontSize() / 2 + "pt;";

                    if (cr.isBold())
                        fontStyle += "font-weight:bold;";
                    if (cr.isItalic())
                        fontStyle += "font-style:italic;";*/

                    htmlText += fontStyle + "\">" + tempString + cr.text() + "</span>";
                    tempString = "";
                }
            }
        }

        htmlText += tempString+"</div>";
//        writeFile(htmlText);
        return htmlText;
    }

    /**doc
     * 读写文档中的表格
     *
     * @param it
     * @param rangetbl
     * @throws Exception
     */
    public void readTable(TableIterator it, Range rangetbl) throws Exception {

        htmlTextTbl="";
        //迭代文档中的表格

        counter=-1;
        while (it.hasNext())
        {
            tblExist=true;
            htmlTextTbl="";
            Table tb = (Table) it.next();
            beginPosi=tb.getStartOffset() ;
            endPosi=tb.getEndOffset();

            System.out.println("............"+beginPosi+"...."+endPosi);
            counter=counter+1;
            //迭代行，默认从0开始
            beginArray[counter]=beginPosi;
            endArray[counter]=endPosi;

            htmlTextTbl+="<table border>";
            for (int i = 0; i < tb.numRows(); i++) {
                TableRow tr = tb.getRow(i);

                htmlTextTbl+="<tr>";
                //迭代列，默认从0开始
                for (int j = 0; j < tr.numCells(); j++) {
                    TableCell td = tr.getCell(j);//取得单元格
                    int cellWidth=td.getWidth();

                    //取得单元格的内容
                    for(int k=0;k<td.numParagraphs();k++){
                        Paragraph para =td.getParagraph(k);
                        String s = para.text().toString().trim();
                        if(s=="")
                        {
                            s=" ";
                        }
                        System.out.println(s);
                        htmlTextTbl += "<td width="+cellWidth+ ">"+s+"</td>";
                        System.out.println(i+":"+j+":"+cellWidth+":"+s);
                    } //end for
                }   //end for
            }   //end for
            htmlTextTbl+="</table>" ;
            htmlTextArray[counter]=htmlTextTbl;

        } //end while
    }

    /**doc
     * 读写文档中的图片
     *
     * @param pTable
     * @param cr
     * @throws Exception
     */
    public void readPicture(PicturesTable pTable, CharacterRun cr) throws Exception {
        // 提取图片
        Picture pic = pTable.extractPicture(cr, false);
        // 返回POI建议的图片文件名
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd+HH-mm-ss");
        String afileName = sdf.format(new Date())+"+"+pic.suggestFullFileName();
        File file = new File(imgPath);
        if (!file.exists()){
            file.mkdirs();
        }
        OutputStream out = new FileOutputStream(new File(imgPath + File.separator + afileName));
        pic.writeImageContent(out);
        System.out.println(imgPath);
        htmlText += "<img src=\"/img/word/" + afileName + "\"/>";
    }

    public boolean compareCharStyle(CharacterRun cr1, CharacterRun cr2)
    {
        boolean flag = false;
        if (cr1.isBold() == cr2.isBold() && cr1.isItalic() == cr2.isItalic() && cr1.getFontName().equals(cr2.getFontName()) && cr1.getFontSize() == cr2.getFontSize())
        {
            flag = true;
        }
        return flag;
    }


    /**doc
     * 写文件
     *
     * @param s
     */
    public void writeFile(String s) {
        FileOutputStream fos = null;
        BufferedWriter bw = null;
        try {
            File file = new File("abc.html");
            fos = new FileOutputStream(file);
            bw = new BufferedWriter(new OutputStreamWriter(fos));
            bw.write(s);
        } catch (FileNotFoundException fnfe) {
            fnfe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            try {
                if (bw != null)
                    bw.close();
                if (fos != null)
                    fos.close();
            } catch (IOException ie) {
            }
        }
    }


}
